package com.flydog.mall.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.flydog.mall.dto.BucketPolicyConfigDto;
import com.flydog.mall.dto.FileUploadDto;
import com.flydog.mall.service.FileManageService;
import io.minio.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Minio 对象存储
 *
 * @author AI
 */
@Slf4j
@Service
public class MinioFileManageImpl implements FileManageService {

    @Value("${minio.endpoint}")
    private String ENDPOINT;

    @Value("${minio.bucketName}")
    private String BUCKET_NAME;

    @Value("${minio.accessKey}")
    private String ACCESS_KEY;

    @Value("${minio.secretKey}")
    private String SECRET_KEY;

    /**
     * @param file 上传的文件
     * @return 文件属性
     * @throws Exception 各种异常
     */
    @Override
    public FileUploadDto upload(MultipartFile file, String moduleName, String instanceName, String contentName) throws Exception {

        MinioClient minioClient = MinioClient.builder()
                .endpoint(ENDPOINT)
                .credentials(ACCESS_KEY, SECRET_KEY)
                .build();
        boolean isExist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(BUCKET_NAME).build());
        if (!isExist) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(BUCKET_NAME).build());
            BucketPolicyConfigDto policyConfigDto = createBucketPolicyConfigDto(BUCKET_NAME);
            SetBucketPolicyArgs policyArgs = SetBucketPolicyArgs.builder()
                    .bucket(BUCKET_NAME)
                    .config(JSONUtil.toJsonStr(policyConfigDto))
                    .build();
            minioClient.setBucketPolicy(policyArgs);
        } else {
            log.info("存储桶已经存在！");
        }
        String fileName = file.getOriginalFilename();
        String objectName = createObjectName(fileName, moduleName, instanceName, contentName);
        PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                .bucket(BUCKET_NAME)
                .object(objectName)
                .contentType(file.getContentType())
                .stream(file.getInputStream(), file.getSize(), ObjectWriteArgs.MIN_MULTIPART_SIZE)
                .build();
        minioClient.putObject(putObjectArgs);
        log.info("文件{}上传成功", objectName);
        FileUploadDto dto = new FileUploadDto();
        dto.setName(fileName);
        dto.setUrl(ENDPOINT + BUCKET_NAME + "/" + objectName);
        return dto;
    }

    @Override
    public void delete(String objectName) throws Exception {
        MinioClient minioClient = MinioClient.builder()
                .endpoint(ENDPOINT)
                .credentials(ACCESS_KEY, SECRET_KEY)
                .build();
        minioClient.removeObject(RemoveObjectArgs.builder().bucket(BUCKET_NAME).object(objectName).build());
        log.info("文件{}删除成功", objectName);
    }

    private BucketPolicyConfigDto createBucketPolicyConfigDto(String bucketName) {
        BucketPolicyConfigDto.Statement statement = BucketPolicyConfigDto.Statement.builder()
                .Effect("Allow")
                .Principal("*")
                .Action("s3:GetObject")
                .Resource("arn:aws:s3:::" + bucketName + "/*.**").build();
        return BucketPolicyConfigDto.builder()
                .Version("2012-10-17")
                .Statement(CollUtil.toList(statement))
                .build();

    }

    @Override
    public void deleteByUrl(String objectUrl) throws Exception {
        if (!StrUtil.isBlankIfStr(objectUrl)) {
            String objectName = convertUrlToObjectName(objectUrl);
            delete(objectName);
        }
    }

    private String convertUrlToObjectName(String url) {
        int index = url.lastIndexOf(BUCKET_NAME);
        return url.substring(index + BUCKET_NAME.length() + 1);
    }

    private String createObjectName(String originalFileName, String moduleName, String instanceName, String contentName) {
        String postfix = originalFileName.substring(originalFileName.lastIndexOf("."));
        return moduleName + "/" + instanceName + "/" + contentName + postfix;
    }
}
